<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>类的基础知识</title>
</head>
<body>
    
</body>
</html>

<script>
    //声明定义
    //可以使用类的声明和赋值表达式来定义类，推荐使用类声明类定义类
    //类声明
    // class User{

    // }
    // console.log(new User());

    // let Article = class{};
    // console.log(new Article());

    //类方法间不需要逗号
    // class User{
    //     show(){}
    //     get(){
    //         console.log("get method")
    //     }
    // }
    // const hd = new User();
    // hd.get();

    //构造函数
    //使用constructor构造函数传递参数   下面的show为构造函数方法，getName为类的原型方法
    //constructor 会在new 的时候自动执行
    // class User{
    //     //实例化的时候自动执行
    //     constructor(name){
    //         this.name = name;
    //         this.show = function(){}
    //     }
    //     getName(){
    //         return this.name;
    //     }
    // }
    // const xj = new User("向军大叔");
    // console.log(xj.getName());

    //原理分析
    //类其实是函数
    // class User{

    // }
    // console.log(typeof User);
    // console.dir(User);

    //constructor用于定义函数代码，下面是普通函数和类函数的对比，结构是一致的
    // class User{
    //     constructor(name){
    //         this.name = name;
    //     }
    //     show(){}
    // }

    // console.dir(User == User.prototype.constructor);

    //下面是对比的普通函数
    // function Hd(name){
    //     this.name = name;
    // }
    // console.dir(Hd);
    // console.log(Hd == Hd.prototype.constructor);
    //在类中定义的方法也是保存在函数原型中的
    // console.dir(User);

    //获取原型中的方法名称
    // console.log(Object.getOwnPropertyNames(User.prototype));

    //所以定义下面的的类 和下面使用函数的定义是一致的
    // class User{
    //     constructor(name){
    //         this.name = name;
    //     }
    //     show(){
    //         console.log(this.name);
    //     }
    // }

    // //和下面使用函数的定义是一致的
    // function Users(name){
    //     this.name = name;
    // }
    // Users.prototype.show = function(){
    //     console.log(this.name)
    // }

    //属性定义
    // class User{
    //     site = "后盾人";
    //     constructor(name) {
    //         this.name = name;
    //     }
    //     show(){
    //         console.log(this.site + ":" + this.name);
    //     }
    //     setSite(value){
    //         this.site = value;
    //     }
    // }
    // let hd = new User("向军");
    // hd.setSite("hdcms");
    // console.log(hd.show());


    //函数差异
    //class 是使用函数声明类的语法糖，但是还是有所区别
    //class中定义的方法不能枚举
    // class User{
    //     constructor(name,age) {
    //         this.name = name;
    //         this.age = age;
    //     }
    //     show(){
    //         console.log(this.name);
    //     }
    // }
    //
    // let xj = new User("向军",22);
    // console.log(Object.getOwnPropertyDescriptors(xj.constructor));
    //这边不会枚举出show属性
    //也就是不会去查找原型链上的方法
    // for(const key in xj){
    //     console.log(key);
    // }

    // function Hd(name) {
    //     this.name = name;
    // }
    // Hd.prototype.show = function(){
    //     console.log(this.name);
    // }
    // let obj = new Hd('后盾人');
    // for(const key in obj){
    //     console.log(key);
    // }

    //严格模式
    //class 默认使用strict  严格模式执行
    // class User{
    //     constructor(name) {
    //         this.name = name;
    //     }
    //     show(){
    //         function test(){
    //             //严格模式下输出undefined
    //             console.log(this);
    //         }
    //         test();
    //     }
    // }
    //
    // let xj = new User("向军");
    // xj.show()


    //一般情况下要使用严格模式 这样会让程序更加的健壮

    //使用普通的函数定义
    // function Hd(name){
    //     this.name = name;
    // }
    //
    // "use strict";
    // Hd.prototype.show = function(){
    //     function test(){
    //         //非严格模式下输出window
    //         console.log(this);
    //     }
    //     test();
    // };
    // let obj = new Hd("后盾人");
    // obj.show();

    //所以使用class 语法糖定义方法的时候，默认是处理了很多问题的

    //静态访问
    //静态属性
    //静态属性是为类设置的属性   而不是为生成的对象设置的

    // function User(){}
    // User.site = "后盾人";
    // // console.dir(User);
    //
    // const hd = new User();
    // // console.log(hd.constructor.site);
    // console.log(User.site);


    //在class中为属性添加static关键字即声明为静态属性
    // class Request{
    //     //静态属性，所有的实例化对象公用的，改变一个就相当于是改变了所有
    //     static HOST = 'http://www.houdunren.com';
    //     //query是对象方法   各自是各自的
    //     query(api){
    //         return Request.HOST + "/" + api;
    //     }
    // }

    //静态方法，修改一个，两个都修改了
    // let request = new Request();
    // let request1 = new Request();
    // request.constructor.HOST = 'hdcms.com';
    // console.log(request.constructor.HOST);
    // console.log(request1.constructor.HOST);
    // console.log(request.query('api/houdunren'));
    // console.log(request1.query('api/hdcms'));

    // console.dir(request);


    //静态方法

    // function User(){
    //     this.show = function () {
    //         return 'this is a object function';
    //     };
    // }
    //
    // //添加静态方法
    // User.show = function () {
    //     return "welcome to houdunren";
    // }
    //
    // const xj = new User();
    // console.log(xj.show());
    // console.log(User.show())

    //在class内声明的方法使用static关键字定义  的就是静态方法
    // class User{
    //     constructor(name) {
    //         this.name = name;
    //     }
    //     static create(name){
    //         return new User(name);
    //     }
    // }
    //
    // const xj = User.create('向军大叔');
    // console.log(xj);

    //使用静态方法在课程类中的使用
    // const data = [
    //     {name : "js" , price : 100},
    //     {name: "mysql",price: 212},
    //     {name: "vue.js",price: 98}
    // ];




    //其实就是一句化   当要被单个对象使用的时候  使用普通的方法和变量   如果要是要操作所有的对象   就要使用static 在原型上进行方法定义
    // class Lesson{
    //     //初始化数据
    //     constructor(data) {
    //         this.model = data;
    //     }
    //     //对单个对象进行处理，使用这种方式声明
    //     get price(){
    //         return this.model.price;
    //     }
    //     get name(){
    //         return this.model.name;
    //     }
    //
    //     //批量生成对象
    //     //不是只给当前对象使用的要使用静态方法
    //     static createBatch(data){
    //         return data.map(item => new Lesson(item));
    //     }
    //
    //     //最贵的课程
    //     static MaxPrice(collection){
    //         return collection.sort((a,b) => b.price - a.price)[0];
    //     }
    // }

    /*
    // const lessons = Lesson.createBatch(data);
    // console.log(lessons);
    //计算加哥最高的课程
    // console.log(Lesson.MaxPrice(lessons).name);
    */

    //获取mysql的价格
    // let mysql = new Lesson({name:'mysql',price:500});
    // console.log(mysql.name);




</script>